/**
 * Copyright(c) 2014 Xunton Solutions
 *
 * History:
 *   15-5-6 上午10:36 Created by dwzhang
 */
package com.jade.bss.business.order.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.jade.bss.base.BssException;
import com.jade.bss.business.order.Order;
import com.jade.bss.business.order.OrderDao;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.criterion.sql.SqlUtils;
import com.jade.framework.base.util.PagingList;
import com.jade.framework.base.util.Parameters;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;

/**
 * 采用JPA方式实现的订单数据访问接口。
 *
 * @author <a href="mailto:dwzhang@xunton.com">dwzhang</a> 
 * @version 1.0 15-5-6 上午10:36
 */
@Named ("bss_orderDao")
public class JpaOrderDao
        implements OrderDao
{
    private static final String SQL = "SELECT bssOrder FROM com.jade.bss.business.order.Order bssOrder";
    @PersistenceContext (unitName = "default")
    protected EntityManager em;

    @Caching (evict = {@CacheEvict (value = "bss.order.g", key = "#order.id"),
            @CacheEvict (value = "bss.order.qc", key = "#order.customerId + '[%GRP%]'"),
            @CacheEvict (value = "bss.order.q", allEntries = true)})
    public void add(Order order)
            throws BssException
    {
        em.persist(order);
    }

    @Caching (evict = {@CacheEvict (value = "bss.order.g", key = "#order.id"),
            @CacheEvict (value = "bss.order.qc", key = "#order.customerId + '[%GRP%]'"),
            @CacheEvict (value = "bss.order.q", allEntries = true)})
    public void update(Order order)
            throws BssException
    {
        em.merge(order);
    }

    @Caching (evict = {@CacheEvict (value = "bss.order.g", key = "#order.id"),
            @CacheEvict (value = "bss.order.qc", key = "#order.customerId + '[%GRP%]'"),
            @CacheEvict (value = "bss.order.q", allEntries = true)})
    public int update(Order order, Parameters params, int[] statuses)
            throws BssException
    {
        params.remove("id");
        if (params.isEmpty()) {
            throw new IllegalArgumentException("There is one field at least to update");
        }

        StringBuilder hsql = new StringBuilder();
        hsql.append("UPDATE com.jade.bss.business.order.Order SET ");
        Iterator<String> names = params.getNames();
        while (names.hasNext()) {
            String name = names.next();
            hsql.append(name).append("=:").append(name);
            if (names.hasNext()) {
                hsql.append(", ");
            }
            else {
                hsql.append(" ");
            }
        }
        hsql.append("WHERE id=:id ");
        if (statuses != null && statuses.length > 0) {
            hsql.append("AND status in :oldStatus");
        }

        Query query = em.createQuery(hsql.toString());
        names = params.getNames();
        while (names.hasNext()) {
            String name = names.next();
            query.setParameter(name, params.getObject(name));
        }
        if (statuses != null && statuses.length > 0) {
            List<Integer> list = new ArrayList<Integer>();
            for (int status : statuses) {
                list.add(status);
            }
            query.setParameter("oldStatus", list);
        }
        query.setParameter("id", order.getId());
        return query.executeUpdate();
    }

    @Caching (evict = {@CacheEvict (value = "bss.order.g", key = "#order.id"),
            @CacheEvict (value = "bss.order.qc", key = "#order.customerId + '[%GRP%]'"),
            @CacheEvict (value = "bss.order.q", allEntries = true)})
    public void remove(Order order)
            throws BssException
    {
        Order old = em.find(Order.class, order.getId());
        if (old != null) {
            em.remove(old);
        }
    }

    @Cacheable (value = "bss.order.g", key = "#id")
    public Order get(long id)
            throws BssException
    {
        return em.find(Order.class, id);
    }

    @Cacheable (value = "bss.order.qc", key = "#customerId + '[%GRP%]' + #criteria")
    public PagingList<Order> query(long customerId, Criteria criteria)
    {
        criteria.add(Restrictions.eq("bssOrder.customerId", customerId));
        return query(criteria);
    }

    @Cacheable (value = "bss.order.q", key = "#criteria")
    public PagingList<Order> query(Criteria criteria)
    {
        return SqlUtils.sqlQuery(SQL, em, criteria);
    }

//    @Caching (evict = {@CacheEvict (value = "bss.order.lt", key = "#record.orderId")})
//    public void addTrace(TraceRecord record)
//    {
//        em.persist(record);
//    }
//
//    @Cacheable (value = "bss.order.lt", key = "#orderId")
//    public List<TraceRecord> listTrace(long orderId)
//    {
//        String sql = "SELECT record FROM com.jade.bss.business.order.TraceRecord record WHERE orderId=:orderId ORDER BY opDate DESC";
//        Query query = em.createQuery(sql);
//        return query.getResultList();
//    }


    public void updateOrderStatus(long orderId, int orderStatus, double tradePrice)
    {
        String sql = "UPDATE Order SET status=:orderStatus,tradePrice=:tradePrice WHERE id=:orderId";
        Query query = em.createQuery(sql);
        query.setParameter("orderStatus", orderStatus);
        query.setParameter("tradePrice", tradePrice);
        query.setParameter("orderId", orderId);
        query.executeUpdate();
    }
}
